package com.meimeixia.pattern.singleton.demo8;

/**
 * 反射破坏单例模式
 * 静态内部类方式
 * @author: t-zhijiang.zhao
 * @date: 2024/11/26 上午10:30
 */
public class Singleton {

    private static boolean flag = false;


    // 私有化构造方法
    private Singleton(){
        synchronized(Singleton.class){
            // 判断flag的值是否为true，若是true，则说明非第一次访问，直接抛一个异常，若是false，则说明第一次访问，就让该私有构造方法正常的去创建对象即可
            if (flag) {
                throw new RuntimeException("不能创建多个对象");
            }
            // 将flag的值设置为true
            flag = true;
        }
    }

    // 定义一个静态内部类
    private static class SingletonHolder{
        // 在内部类中声明并初始化外部类的对象
        private static final Singleton INSTANCE = new Singleton();
    }

    // 提供公共的访问方式
    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }

    //反射破坏单例模式的解决方案
    /*首先，我们先分析一下反射是如何破坏单例模式的？通过上面反射破坏单例模式的演示，我们就能知道了，就是通过反射去获取Singleton类的私有构造方法，然后再利用该私有构造方法去创建对象，这就是反射破坏单例模式的本质原因。
    接下来，大家就要思索反射破坏单例模式的解决方案了。
    大家不妨开动自己的脑筋想一想，看是不是这样的，如果是第一次调用Singleton类的私有构造方法去创建单实例对象，那么就允许其去创建，当单实例对象创建出来并存在于内存中之后，接下来要是再来调用Singleton类的私有构造方法的话，就直接抛出一个异常即可。
    由于我们是通过静态内部类这种方式来实现单例模式的，所以在Singleton类里面我们就要声明一个静态的布尔类型的变量，判断一下Singleton类的私有构造方法是第一次还是后面几次调用去创建对象的。
    有些同学可能为会问，为什么该布尔类型的变量要是静态的呢？这是因为要让所有的线程（或者锁）所共享。
    */
}
